package example.com.nexd.collectionsdk.sdk.collector.util;

import android.content.Context;
import android.hardware.Sensor;

import java.io.IOException;
import java.util.List;

import example.com.nexd.collectionsdk.sdk.cache.DiskLruCache;
import example.com.nexd.collectionsdk.sdk.collector.Collector;
import example.com.nexd.collectionsdk.sdk.collector.CollectorConfig;
import example.com.nexd.collectionsdk.sdk.collector.CollectorWrap;
import example.com.nexd.collectionsdk.sdk.collector.UserIdUtils;
import example.com.nexd.collectionsdk.sdk.collector.bean.BluetoothDataResult;
import example.com.nexd.collectionsdk.sdk.collector.bean.SensorDataResult;
import example.com.nexd.collectionsdk.sdk.collector.bean.WifiDataResult;
import example.com.nexd.collectionsdk.sdk.collector.core.CollectorTaskFactory;
import example.com.nexd.collectionsdk.sdk.collector.listener.BluetoothCollrctorResultListener;
import example.com.nexd.collectionsdk.sdk.collector.listener.SensorCollectorResultListener;
import example.com.nexd.collectionsdk.sdk.collector.listener.TimerTaskListener;
import example.com.nexd.collectionsdk.sdk.collector.listener.WifiCollectorResultListener;
import example.com.nexd.collectionsdk.sdk.utils.FileUtils;
import example.com.nexd.collectionsdk.sdk.utils.Log;
import example.com.nexd.collectionsdk.sdk.utils.Version;

/**
 * NexdCollectionAgent create by codingfish at 15/5/4
 * TODO:
 *
 * @Version V1.0
 */
public class NexdCollectionAgent {


    private WifiCollectorResultListener wifiCollectorResultListener;
    private BluetoothCollrctorResultListener bluetoothCollectorResultListener;
    private SensorCollectorResultListener sensorCollectorResultListener;
    private CollectorConfig collectorConfig;
    private Context context;

    private CollectorWrap wifiCollector;
    private CollectorWrap bluetoothCollector;
    private CollectorWrap accelerometerSensorCollector;
    private CollectorWrap stepCounterCollector;
    private CollectorWrap gravitySensorCollector;

    private CollectorWrap gyroscopeCollector;
    private CollectorWrap linearAccelerationCollector;
    private CollectorWrap magneticFileldCollector;
    private CollectorWrap orientationCollector;
    private CollectorWrap stepDetectorCollector;
    private CollectorWrap rotationVectorCollector;

    private CollectorWrap gyroscopeUncalibratedCollector;
    private CollectorWrap magneticFieldUncalibratedCollector;
    private CollectorWrap geomagneticRotationVectorCollector;
    private CollectorWrap gameRotationVectorCollector;

    private String userId = "";

    private DiskLruCache diskLruCache;

    private NexdCollectionAgent() {
    }

    public static NexdCollectionAgent getInstance() {

        return SingletonHolder.getInstance();
    }


    private static class SingletonHolder {
        private static NexdCollectionAgent instance = new NexdCollectionAgent();

        public static NexdCollectionAgent getInstance() {
            return instance;
        }
    }

    /**
     * 设置 Wifi 结果回调。
     *
     * @param wifiCollectorResultListener
     * @see cn.nexd.collection.collector.bean.WifiDataResult
     */
    public void setWifiCollectorResultListener(WifiCollectorResultListener wifiCollectorResultListener) {

        this.wifiCollectorResultListener = wifiCollectorResultListener;
    }

    /**
     * 设置 Bluetooth 结果回调。
     *
     * @param bluetoothCollectorResultListener
     * @see cn.nexd.collection.collector.bean.BluetoothDataResult
     */
    public void setBluetoothCollectorResultListener(BluetoothCollrctorResultListener bluetoothCollectorResultListener) {
        this.bluetoothCollectorResultListener = bluetoothCollectorResultListener;
    }

    /**
     * 设置传感器结果回调。
     *
     * @param sensorCollectorResultListener
     * @see cn.nexd.collection.collector.bean.BluetoothDataResult
     */

    public void setSensorCollectorResultListener(SensorCollectorResultListener sensorCollectorResultListener) {
        this.sensorCollectorResultListener = sensorCollectorResultListener;
    }

    /**
     * 设置配置对象。
     *
     * @param collectorConfig
     * @see cn.nexd.collection.collector.CollectorConfig
     */
    public void setCollectorConfig(CollectorConfig collectorConfig) {
        this.collectorConfig = collectorConfig;
    }

    /**
     * 设置 Context 对象。SDK 运行的基础，不能设置为 null。
     *
     * @param context
     * @see Context
     */
    public void setContext(Context context) {
        this.context = context;
    }

    /**
     * 获取用户 ID。该 ID 用于唯一的标识用户，全局唯一。
     * 如果 context 为 null 且 setContent 没有在 getUserId 之前被显式调用， 则返回""
     *
     * @param context
     */
    public String getUserId(Context context) {
        if (context == null & this.context == null) {
            return "";
        }
        return "".equals(userId) ? UserIdUtils.getInstance().getUserId(context) : userId;
    }

    /**
     * 启动采集器。
     *
     * @throws IllegalAccessException
     */
    public void startCollection() throws IllegalAccessException {

        checkParameter();

        if (collectorConfig.collection_mode == Collector.COLLECTION_MODE_PASSIVE) {
            try {
                diskLruCache = DiskLruCache.open(FileUtils.getDiskCacheDir(context, "nextdirection"), Version.VERSION_CODE, 1, 10 * 1024 * 1024);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        configCollector();
        UserIdUtils.getInstance().setTimerTaskListener(new NexdTimerTaskListener());
        UserIdUtils.getInstance().startTaskId(collectorConfig, context);
    }

    public void stopCollection() {

        if (collectorConfig.wifi_available) {
            wifiCollector.stopCollector();
        }

        if (collectorConfig.bluetooth_available) {
            bluetoothCollector.stopCollector();
        }

        if (collectorConfig.sensor_available) {
            accelerometerSensorCollector.stopCollector();
            stepCounterCollector.stopCollector();
            gravitySensorCollector.stopCollector();
            gyroscopeCollector.stopCollector();
            linearAccelerationCollector.stopCollector();
            magneticFileldCollector.stopCollector();
            orientationCollector.stopCollector();
            rotationVectorCollector.stopCollector();
            stepDetectorCollector.stopCollector();
            gyroscopeUncalibratedCollector.stopCollector();
            magneticFieldUncalibratedCollector.stopCollector();
            geomagneticRotationVectorCollector.stopCollector();

            gameRotationVectorCollector.stopCollector();
        }


        UserIdUtils.getInstance().stopTaskId();
    }

    /*
    * 根据 CollectorConfig 配置，生成采集器对象。CollectorConfig中已经为主动模式和被动模式做好区分，即：主动模式下所有采集器默认全部打开，
    * 被动模式下只有 Wifi 可用。如果用户在被动模式下显式设置 Wifi 不可用，则将没有采集器参与到工作中去。同样的，在主动模式下，如果用户显式的
    * 设置 Wifi、Bluetooth、Sensor 不可用，也将没有采集器参与到采集工作。
    * */
    private void configCollector() {


        if (collectorConfig.wifi_available) {
            wifiCollector = new CollectorWrap(CollectorTaskFactory.getWifiCollectorTask(context, new DefaultWifiCollectorListener(), collectorConfig));
            wifiCollector.startCollector();
        }

        if (collectorConfig.bluetooth_available) {
            bluetoothCollector = new CollectorWrap(CollectorTaskFactory.getBluetoothCollectorTask(context, new DefaultBluetoothCollectorResultListener(), collectorConfig));
            bluetoothCollector.startCollector();
        }

        if (collectorConfig.sensor_available) {
            accelerometerSensorCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_ACCELEROMETER, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            accelerometerSensorCollector.startCollector();
            stepCounterCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_STEP_COUNTER, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            stepCounterCollector.startCollector();
            gravitySensorCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_GRAVITY, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            gravitySensorCollector.startCollector();
            gyroscopeCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_GYROSCOPE, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            gyroscopeCollector.startCollector();
            linearAccelerationCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_LINEAR_ACCELERATION, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            linearAccelerationCollector.startCollector();
            magneticFileldCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_MAGNETIC_FIELD, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            magneticFileldCollector.startCollector();
            orientationCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_ORIENTATION, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            orientationCollector.startCollector();
            rotationVectorCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_ROTATION_VECTOR, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            rotationVectorCollector.startCollector();
            stepDetectorCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_STEP_DETECTOR, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            stepDetectorCollector.startCollector();
            gyroscopeUncalibratedCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            gyroscopeUncalibratedCollector.startCollector();
            magneticFieldUncalibratedCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            magneticFieldUncalibratedCollector.startCollector();
            geomagneticRotationVectorCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            geomagneticRotationVectorCollector.startCollector();
            gameRotationVectorCollector = new CollectorWrap(CollectorTaskFactory.getSensorCollectorTask(Sensor.TYPE_GAME_ROTATION_VECTOR, context, new DefaultSensorCollectorResultListener(), collectorConfig));
            gameRotationVectorCollector.startCollector();
        }
    }

    private void checkParameter() throws IllegalArgumentException {
        //如果setContext没有被显式调用，则抛出IllegalArgumentException的运行时异常。
        if (context == null) {
            throw new IllegalArgumentException("Context can not be null");
        }

        if (collectorConfig == null) {
            collectorConfig = new CollectorConfig.Builder().build();
        }

        
    }


    /*实现中转的监听回调。其作用是根据采集模式分发业务：主动模式实时上传，在一个采集周期内实时上传。被动模式只采集 wifi，定时上传*/
    private final class DefaultBluetoothCollectorResultListener implements BluetoothCollrctorResultListener {

        @Override
        public void onSuccess(String scanId, BluetoothDataResult bluetoothDataResult) {

            if (bluetoothCollectorResultListener != null) {
                bluetoothCollectorResultListener.onSuccess(scanId, bluetoothDataResult);
            }

            ActiveModeDataUtil.getInstance().setBluetoothData(bluetoothDataResult);
        }


        @Override
        public void onFailed(String scanId, int faied_id, String message) {
            if (bluetoothCollectorResultListener != null) {
                bluetoothCollectorResultListener.onFailed(scanId, faied_id, message);
            }
        }
    }

    private final class DefaultSensorCollectorResultListener implements SensorCollectorResultListener {
        @Override
        public void onSuccess(String scanId, SensorDataResult sensorDataResult) {
            if (sensorCollectorResultListener != null) {
                sensorCollectorResultListener.onSuccess(scanId, sensorDataResult);
            }

            ActiveModeDataUtil.getInstance().setSensorData(sensorDataResult);

//            Log.d(DefaultSensorCollectorResultListener.class.getSimpleName(), "" + sensorDataResult.getSensor());
        }

        @Override
        public void onAccuracyChanged(String scanId, Sensor sensor, int accuracy) {
            if (sensorCollectorResultListener != null) {
                sensorCollectorResultListener.onAccuracyChanged(scanId, sensor, accuracy);
            }

            ActiveModeDataUtil.getInstance().setSensorAccuracyChanged(sensor, accuracy);
        }

        @Override
        public void onFailed(String scanId, int faied_id, String message) {
            if (sensorCollectorResultListener != null) {
                sensorCollectorResultListener.onFailed(scanId, faied_id, message);
            }
        }
    }

    private final class DefaultWifiCollectorListener implements WifiCollectorResultListener {
        @Override
        public void onSuccess(String scanId, List<WifiDataResult> wifiDataResults) {
            if (wifiCollectorResultListener != null) {
                wifiCollectorResultListener.onSuccess(scanId, wifiDataResults);
            }

            if (collectorConfig.collection_mode == Collector.COLLECTION_MODE_PASSIVE) {
                /*被动采集，只有 wifi 参与采集，定时打包上传*/
                PassiveModeDataUtil.getInstance(getUserId(context), scanId, diskLruCache).cacheWifiData(wifiDataResults);
            } else {
                /*主动采集*/
                ActiveModeDataUtil.getInstance().setWifiData(wifiDataResults);
            }
        }

        @Override
        public void onFailed(String scanId, int faied_id, String message) {
            if (wifiCollectorResultListener != null) {
                wifiCollectorResultListener.onFailed(scanId, faied_id, message);
            }
            Log.d(DefaultWifiCollectorListener.class.getSimpleName(), "## onFailed");

        }
    }


    private class NexdTimerTaskListener implements TimerTaskListener {

        @Override
        public void timerTaskCallback(String task_Id) {
            /*采集开始的 ID，之后所有通过结果回调的 id 都在这个采集周期内，应该是相同的。*/
            ActiveModeDataUtil.getInstance().setScanId(task_Id);
            ActiveModeDataUtil.getInstance().setUserId(UserIdUtils.getInstance().getUserId(context));
            ActiveModeDataUtil.getInstance().handlerData();
        }
    }
}
